package cn.renhui.hermesbus.core;

import android.text.TextUtils;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

import cn.renhui.hermesbus.utils.LogUtils;
import cn.renhui.hermesbus.utils.TypeUtils;
import cn.renhui.hermesbus.bean.RequestBean;
import cn.renhui.hermesbus.bean.RequestParameter;

public class TypeCenter {

    private static final TypeCenter instance = new TypeCenter();

    private final ConcurrentHashMap<String, Class<?>> mRawClass;
    private final ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Method>> mRawMethod;

    private TypeCenter() {
        mRawClass = new ConcurrentHashMap<>();
        mRawMethod = new ConcurrentHashMap<>();
    }

    public static TypeCenter getInstance() {
        return instance;
    }

    public void register(Class<?> clazz) {
        registerClass(clazz);
        registerMethod(clazz);
    }

    private void registerClass(Class<?> clazz) {
        String className = clazz.getName();
        LogUtils.e("Register Class :" + className);
        mRawClass.putIfAbsent(className, clazz);
    }

    private void registerMethod(Class<?> clazz) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            mRawMethod.putIfAbsent(clazz, new ConcurrentHashMap<>());
            ConcurrentHashMap<String, Method> map = mRawMethod.get(clazz);
            String key = TypeUtils.getMethodId(method);
            LogUtils.e("Register Method :" + key);
            map.putIfAbsent(key, method);
        }
    }

    public Class<?> getClassType(String name) {
        if (TextUtils.isEmpty(name)) {
            return null;
        }
        Class<?> clazz = mRawClass.get(name);
        if (clazz == null) {
            try {
                clazz = Class.forName(name);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return clazz;
    }

    public Method getMethod(Class<?> aClass, RequestBean requestBean) {
        String methodName = requestBean.getMethodName();//setFriend()
        if (methodName != null) {
            mRawMethod.putIfAbsent(aClass, new ConcurrentHashMap<String, Method>());
            ConcurrentHashMap<String, Method> methods = mRawMethod.get(aClass);
            Method method = methods.get(methodName);
            if(method != null){
                return method;
            }
            int pos = methodName.indexOf('(');

            Class[] paramters = null;
            RequestParameter[] requestParameters = requestBean.getRequestParameters();
            if (requestParameters != null && requestParameters.length > 0) {
                paramters = new Class[requestParameters.length];
                for (int i=0;i<requestParameters.length;i++) {
                    paramters[i]=getClassType(requestParameters[i].getParameterClassName());
                }
            }
            method = TypeUtils.getMethod(aClass, methodName.substring(0, pos), paramters);
            methods.put(methodName, method);
            return method;
        }
        return null;
    }

}
